package com.netty.nio.demo3;

import com.netty.util.ByteBufferUtil;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Set;

import static com.netty.util.ByteBufferUtil.debugAll;

public class ServerApplication {

  public static void main(String[] args) throws IOException {

    Selector selector = Selector.open(); // 创建选择器
    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

    serverSocketChannel.bind(new InetSocketAddress(8081));

    serverSocketChannel.configureBlocking(false); // 通道必须是非阻塞的

    serverSocketChannel.register(
        selector, SelectionKey.OP_ACCEPT); // 把channel注册到selector，并选择accept事件

    try {
      while (true) {

        int count = selector.select(); // 选择事件，此时会阻塞，当事件发生时会自动解除阻塞

        Set<SelectionKey> selectionKeys = selector.selectedKeys();
        Iterator<SelectionKey> iterator = selectionKeys.iterator();

        while (iterator.hasNext()){
          SelectionKey selectionKey = iterator.next();
          if (selectionKey.isAcceptable()) { // 处理accept事件
            try {
              ServerSocketChannel serverSocket = (ServerSocketChannel) selectionKey.channel();
              System.out.println("已连接");

              SocketChannel socketChannel = serverSocket.accept();
              socketChannel.configureBlocking(false);
              socketChannel.register(selector, SelectionKey.OP_READ); // 读事件
              iterator.remove();

            } catch (IOException e) {

            }
          } else if (selectionKey.isReadable()) { // 处理read事件
            // 获取socketChannel,实际上这个channel就是上面注册进selector的对象
            SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
            ByteBuffer byteBuffer = ByteBuffer.allocate(100);
            try{
              int read = socketChannel.read(byteBuffer);
              System.out.println("read:"+read);
            }catch (Exception e){
//              e.printStackTrace();
             continue;  //一定要这样写。。。。。。。防止多次read报错
            }
            byteBuffer.flip();
            debugAll(byteBuffer);
            byteBuffer.clear();
            iterator.remove();

          }

        }

      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
